//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension IVS {
    // MARK: Enums

    public enum ChannelLatencyMode: String, CustomStringConvertible, Codable, _SotoSendable {
        case low = "LOW"
        case normal = "NORMAL"
        public var description: String { return self.rawValue }
    }

    public enum ChannelType: String, CustomStringConvertible, Codable, _SotoSendable {
        case basic = "BASIC"
        case standard = "STANDARD"
        public var description: String { return self.rawValue }
    }

    public enum RecordingConfigurationState: String, CustomStringConvertible, Codable, _SotoSendable {
        case active = "ACTIVE"
        case createFailed = "CREATE_FAILED"
        case creating = "CREATING"
        public var description: String { return self.rawValue }
    }

    public enum RecordingMode: String, CustomStringConvertible, Codable, _SotoSendable {
        case disabled = "DISABLED"
        case interval = "INTERVAL"
        public var description: String { return self.rawValue }
    }

    public enum StreamHealth: String, CustomStringConvertible, Codable, _SotoSendable {
        case healthy = "HEALTHY"
        case starving = "STARVING"
        case unknown = "UNKNOWN"
        public var description: String { return self.rawValue }
    }

    public enum StreamState: String, CustomStringConvertible, Codable, _SotoSendable {
        case live = "LIVE"
        case offline = "OFFLINE"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct AudioConfiguration: AWSDecodableShape {
        /// Number of audio channels.
        public let channels: Int64?
        /// Codec used for the audio encoding.
        public let codec: String?
        /// Number of audio samples recorded per second.
        public let sampleRate: Int64?
        /// The expected ingest bitrate (bits per second). This is configured in the encoder.
        public let targetBitrate: Int64?

        public init(channels: Int64? = nil, codec: String? = nil, sampleRate: Int64? = nil, targetBitrate: Int64? = nil) {
            self.channels = channels
            self.codec = codec
            self.sampleRate = sampleRate
            self.targetBitrate = targetBitrate
        }

        private enum CodingKeys: String, CodingKey {
            case channels
            case codec
            case sampleRate
            case targetBitrate
        }
    }

    public struct BatchError: AWSDecodableShape {
        /// Channel ARN.
        public let arn: String?
        /// Error code.
        public let code: String?
        /// Error message, determined by the application.
        public let message: String?

        public init(arn: String? = nil, code: String? = nil, message: String? = nil) {
            self.arn = arn
            self.code = code
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case code
            case message
        }
    }

    public struct BatchGetChannelRequest: AWSEncodableShape {
        /// Array of ARNs, one per channel.
        public let arns: [String]

        public init(arns: [String]) {
            self.arns = arns
        }

        public func validate(name: String) throws {
            try self.arns.forEach {
                try validate($0, name: "arns[]", parent: name, max: 128)
                try validate($0, name: "arns[]", parent: name, min: 1)
                try validate($0, name: "arns[]", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
            }
            try self.validate(self.arns, name: "arns", parent: name, max: 50)
            try self.validate(self.arns, name: "arns", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case arns
        }
    }

    public struct BatchGetChannelResponse: AWSDecodableShape {
        public let channels: [Channel]?
        /// Each error object is related to a specific ARN in the request.
        public let errors: [BatchError]?

        public init(channels: [Channel]? = nil, errors: [BatchError]? = nil) {
            self.channels = channels
            self.errors = errors
        }

        private enum CodingKeys: String, CodingKey {
            case channels
            case errors
        }
    }

    public struct BatchGetStreamKeyRequest: AWSEncodableShape {
        /// Array of ARNs, one per channel.
        public let arns: [String]

        public init(arns: [String]) {
            self.arns = arns
        }

        public func validate(name: String) throws {
            try self.arns.forEach {
                try validate($0, name: "arns[]", parent: name, max: 128)
                try validate($0, name: "arns[]", parent: name, min: 1)
                try validate($0, name: "arns[]", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:stream-key/[a-zA-Z0-9-]+$")
            }
            try self.validate(self.arns, name: "arns", parent: name, max: 50)
            try self.validate(self.arns, name: "arns", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case arns
        }
    }

    public struct BatchGetStreamKeyResponse: AWSDecodableShape {
        public let errors: [BatchError]?
        public let streamKeys: [StreamKey]?

        public init(errors: [BatchError]? = nil, streamKeys: [StreamKey]? = nil) {
            self.errors = errors
            self.streamKeys = streamKeys
        }

        private enum CodingKeys: String, CodingKey {
            case errors
            case streamKeys
        }
    }

    public struct Channel: AWSDecodableShape {
        /// Channel ARN.
        public let arn: String?
        /// Whether the channel is private (enabled for playback authorization). Default: false.
        public let authorized: Bool?
        /// Channel ingest endpoint, part of the definition of an ingest server, used when you set up streaming software.
        public let ingestEndpoint: String?
        /// Channel latency mode. Use NORMAL to broadcast and deliver live video up to Full HD. Use LOW for near-real-time interaction with viewers. Default: LOW. (Note: In the Amazon IVS console, LOW and NORMAL correspond to Ultra-low and Standard, respectively.)
        public let latencyMode: ChannelLatencyMode?
        /// Channel name.
        public let name: String?
        /// Channel playback URL.
        public let playbackUrl: String?
        /// Recording-configuration ARN. A value other than an empty string indicates that recording is enabled. Default: "" (empty string, recording is disabled).
        public let recordingConfigurationArn: String?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?
        /// Channel type, which determines the allowable resolution and bitrate. If you exceed the allowable resolution or bitrate, the stream probably will disconnect immediately. Default: STANDARD. Valid values:    STANDARD: Video is transcoded: multiple qualities are generated from the original input, to automatically give viewers the best experience for their devices and network conditions. Transcoding allows higher playback quality across a range of download speeds. Resolution can be up to 1080p and bitrate can be up to 8.5 Mbps. Audio is transcoded only for renditions 360p and below; above that, audio is passed through. This is the default.    BASIC: Video is transmuxed: Amazon IVS delivers the original input to viewers. The viewer’s video-quality choice is limited to the original input. Resolution can be up to 1080p and bitrate can be up to 1.5 Mbps for 480p and up to 3.5 Mbps for resolutions between 480p and 1080p.
        public let type: ChannelType?

        public init(arn: String? = nil, authorized: Bool? = nil, ingestEndpoint: String? = nil, latencyMode: ChannelLatencyMode? = nil, name: String? = nil, playbackUrl: String? = nil, recordingConfigurationArn: String? = nil, tags: [String: String]? = nil, type: ChannelType? = nil) {
            self.arn = arn
            self.authorized = authorized
            self.ingestEndpoint = ingestEndpoint
            self.latencyMode = latencyMode
            self.name = name
            self.playbackUrl = playbackUrl
            self.recordingConfigurationArn = recordingConfigurationArn
            self.tags = tags
            self.type = type
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case authorized
            case ingestEndpoint
            case latencyMode
            case name
            case playbackUrl
            case recordingConfigurationArn
            case tags
            case type
        }
    }

    public struct ChannelSummary: AWSDecodableShape {
        /// Channel ARN.
        public let arn: String?
        /// Whether the channel is private (enabled for playback authorization). Default: false.
        public let authorized: Bool?
        /// Channel latency mode. Use NORMAL to broadcast and deliver live video up to Full HD. Use LOW for near-real-time interaction with viewers. Default: LOW. (Note: In the Amazon IVS console, LOW and NORMAL correspond to Ultra-low and Standard, respectively.)
        public let latencyMode: ChannelLatencyMode?
        /// Channel name.
        public let name: String?
        /// Recording-configuration ARN. A value other than an empty string indicates that recording is enabled. Default: "" (empty string, recording is disabled).
        public let recordingConfigurationArn: String?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?

        public init(arn: String? = nil, authorized: Bool? = nil, latencyMode: ChannelLatencyMode? = nil, name: String? = nil, recordingConfigurationArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.authorized = authorized
            self.latencyMode = latencyMode
            self.name = name
            self.recordingConfigurationArn = recordingConfigurationArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case authorized
            case latencyMode
            case name
            case recordingConfigurationArn
            case tags
        }
    }

    public struct CreateChannelRequest: AWSEncodableShape {
        /// Whether the channel is private (enabled for playback authorization). Default: false.
        public let authorized: Bool?
        /// Channel latency mode. Use NORMAL to broadcast and deliver live video up to Full HD. Use LOW for near-real-time interaction with viewers. (Note: In the Amazon IVS console, LOW and NORMAL correspond to Ultra-low and Standard, respectively.) Default: LOW.
        public let latencyMode: ChannelLatencyMode?
        /// Channel name.
        public let name: String?
        /// Recording-configuration ARN. Default: "" (empty string, recording is disabled).
        public let recordingConfigurationArn: String?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?
        /// Channel type, which determines the allowable resolution and bitrate. If you exceed the allowable resolution or bitrate, the stream probably will disconnect immediately. Default: STANDARD. Valid values:    STANDARD: Video is transcoded: multiple qualities are generated from the original input, to automatically give viewers the best experience for their devices and network conditions. Transcoding allows higher playback quality across a range of download speeds. Resolution can be up to 1080p and bitrate can be up to 8.5 Mbps. Audio is transcoded only for renditions 360p and below; above that, audio is passed through. This is the default.    BASIC: Video is transmuxed: Amazon IVS delivers the original input to viewers. The viewer’s video-quality choice is limited to the original input. Resolution can be up to 1080p and bitrate can be up to 1.5 Mbps for 480p and up to 3.5 Mbps for resolutions between 480p and 1080p.
        public let type: ChannelType?

        public init(authorized: Bool? = nil, latencyMode: ChannelLatencyMode? = nil, name: String? = nil, recordingConfigurationArn: String? = nil, tags: [String: String]? = nil, type: ChannelType? = nil) {
            self.authorized = authorized
            self.latencyMode = latencyMode
            self.name = name
            self.recordingConfigurationArn = recordingConfigurationArn
            self.tags = tags
            self.type = type
        }

        public func validate(name: String) throws {
            try self.validate(self.name, name: "name", parent: name, max: 128)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9-_]*$")
            try self.validate(self.recordingConfigurationArn, name: "recordingConfigurationArn", parent: name, max: 128)
            try self.validate(self.recordingConfigurationArn, name: "recordingConfigurationArn", parent: name, pattern: "^$|^arn:aws:ivs:[a-z0-9-]+:[0-9]+:recording-configuration/[a-zA-Z0-9-]+$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case authorized
            case latencyMode
            case name
            case recordingConfigurationArn
            case tags
            case type
        }
    }

    public struct CreateChannelResponse: AWSDecodableShape {
        public let channel: Channel?
        public let streamKey: StreamKey?

        public init(channel: Channel? = nil, streamKey: StreamKey? = nil) {
            self.channel = channel
            self.streamKey = streamKey
        }

        private enum CodingKeys: String, CodingKey {
            case channel
            case streamKey
        }
    }

    public struct CreateRecordingConfigurationRequest: AWSEncodableShape {
        /// A complex type that contains a destination configuration for where recorded video will be stored.
        public let destinationConfiguration: DestinationConfiguration
        /// Recording-configuration name. The value does not need to be unique.
        public let name: String?
        /// If a broadcast disconnects and then reconnects within the specified interval, the multiple streams will be considered a single broadcast and merged together. Default: 0.
        public let recordingReconnectWindowSeconds: Int?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?
        /// A complex type that allows you to enable/disable the recording of thumbnails for a live session and modify the interval at which thumbnails are generated for the live session.
        public let thumbnailConfiguration: ThumbnailConfiguration?

        public init(destinationConfiguration: DestinationConfiguration, name: String? = nil, recordingReconnectWindowSeconds: Int? = nil, tags: [String: String]? = nil, thumbnailConfiguration: ThumbnailConfiguration? = nil) {
            self.destinationConfiguration = destinationConfiguration
            self.name = name
            self.recordingReconnectWindowSeconds = recordingReconnectWindowSeconds
            self.tags = tags
            self.thumbnailConfiguration = thumbnailConfiguration
        }

        public func validate(name: String) throws {
            try self.destinationConfiguration.validate(name: "\(name).destinationConfiguration")
            try self.validate(self.name, name: "name", parent: name, max: 128)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9-_]*$")
            try self.validate(self.recordingReconnectWindowSeconds, name: "recordingReconnectWindowSeconds", parent: name, max: 300)
            try self.validate(self.recordingReconnectWindowSeconds, name: "recordingReconnectWindowSeconds", parent: name, min: 0)
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
            try self.thumbnailConfiguration?.validate(name: "\(name).thumbnailConfiguration")
        }

        private enum CodingKeys: String, CodingKey {
            case destinationConfiguration
            case name
            case recordingReconnectWindowSeconds
            case tags
            case thumbnailConfiguration
        }
    }

    public struct CreateRecordingConfigurationResponse: AWSDecodableShape {
        public let recordingConfiguration: RecordingConfiguration?

        public init(recordingConfiguration: RecordingConfiguration? = nil) {
            self.recordingConfiguration = recordingConfiguration
        }

        private enum CodingKeys: String, CodingKey {
            case recordingConfiguration
        }
    }

    public struct CreateStreamKeyRequest: AWSEncodableShape {
        /// ARN of the channel for which to create the stream key.
        public let channelArn: String
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?

        public init(channelArn: String, tags: [String: String]? = nil) {
            self.channelArn = channelArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.channelArn, name: "channelArn", parent: name, max: 128)
            try self.validate(self.channelArn, name: "channelArn", parent: name, min: 1)
            try self.validate(self.channelArn, name: "channelArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
            case tags
        }
    }

    public struct CreateStreamKeyResponse: AWSDecodableShape {
        /// Stream key used to authenticate an RTMPS stream for ingestion.
        public let streamKey: StreamKey?

        public init(streamKey: StreamKey? = nil) {
            self.streamKey = streamKey
        }

        private enum CodingKeys: String, CodingKey {
            case streamKey
        }
    }

    public struct DeleteChannelRequest: AWSEncodableShape {
        /// ARN of the channel to be deleted.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, min: 1)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct DeletePlaybackKeyPairRequest: AWSEncodableShape {
        /// ARN of the key pair to be deleted.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, min: 1)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:playback-key/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct DeletePlaybackKeyPairResponse: AWSDecodableShape {
        public init() {}
    }

    public struct DeleteRecordingConfigurationRequest: AWSEncodableShape {
        /// ARN of the recording configuration to be deleted.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:ivs:[a-z0-9-]+:[0-9]+:recording-configuration/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct DeleteStreamKeyRequest: AWSEncodableShape {
        /// ARN of the stream key to be deleted.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, min: 1)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:stream-key/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct DestinationConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// An S3 destination configuration where recorded videos will be stored.
        public let s3: S3DestinationConfiguration?

        public init(s3: S3DestinationConfiguration? = nil) {
            self.s3 = s3
        }

        public func validate(name: String) throws {
            try self.s3?.validate(name: "\(name).s3")
        }

        private enum CodingKeys: String, CodingKey {
            case s3
        }
    }

    public struct GetChannelRequest: AWSEncodableShape {
        /// ARN of the channel for which the configuration is to be retrieved.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, min: 1)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct GetChannelResponse: AWSDecodableShape {
        public let channel: Channel?

        public init(channel: Channel? = nil) {
            self.channel = channel
        }

        private enum CodingKeys: String, CodingKey {
            case channel
        }
    }

    public struct GetPlaybackKeyPairRequest: AWSEncodableShape {
        /// ARN of the key pair to be returned.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, min: 1)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:playback-key/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct GetPlaybackKeyPairResponse: AWSDecodableShape {
        public let keyPair: PlaybackKeyPair?

        public init(keyPair: PlaybackKeyPair? = nil) {
            self.keyPair = keyPair
        }

        private enum CodingKeys: String, CodingKey {
            case keyPair
        }
    }

    public struct GetRecordingConfigurationRequest: AWSEncodableShape {
        /// ARN of the recording configuration to be retrieved.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:ivs:[a-z0-9-]+:[0-9]+:recording-configuration/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct GetRecordingConfigurationResponse: AWSDecodableShape {
        public let recordingConfiguration: RecordingConfiguration?

        public init(recordingConfiguration: RecordingConfiguration? = nil) {
            self.recordingConfiguration = recordingConfiguration
        }

        private enum CodingKeys: String, CodingKey {
            case recordingConfiguration
        }
    }

    public struct GetStreamKeyRequest: AWSEncodableShape {
        /// ARN for the stream key to be retrieved.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, min: 1)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:stream-key/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
        }
    }

    public struct GetStreamKeyResponse: AWSDecodableShape {
        public let streamKey: StreamKey?

        public init(streamKey: StreamKey? = nil) {
            self.streamKey = streamKey
        }

        private enum CodingKeys: String, CodingKey {
            case streamKey
        }
    }

    public struct GetStreamRequest: AWSEncodableShape {
        /// Channel ARN for stream to be accessed.
        public let channelArn: String

        public init(channelArn: String) {
            self.channelArn = channelArn
        }

        public func validate(name: String) throws {
            try self.validate(self.channelArn, name: "channelArn", parent: name, max: 128)
            try self.validate(self.channelArn, name: "channelArn", parent: name, min: 1)
            try self.validate(self.channelArn, name: "channelArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
        }
    }

    public struct GetStreamResponse: AWSDecodableShape {
        public let stream: Stream?

        public init(stream: Stream? = nil) {
            self.stream = stream
        }

        private enum CodingKeys: String, CodingKey {
            case stream
        }
    }

    public struct GetStreamSessionRequest: AWSEncodableShape {
        /// ARN of the channel resource
        public let channelArn: String
        /// Unique identifier for a live or previously live stream in the specified channel. If no streamId is provided, this returns the most recent stream session for the channel, if it exists.
        public let streamId: String?

        public init(channelArn: String, streamId: String? = nil) {
            self.channelArn = channelArn
            self.streamId = streamId
        }

        public func validate(name: String) throws {
            try self.validate(self.channelArn, name: "channelArn", parent: name, max: 128)
            try self.validate(self.channelArn, name: "channelArn", parent: name, min: 1)
            try self.validate(self.channelArn, name: "channelArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
            try self.validate(self.streamId, name: "streamId", parent: name, max: 26)
            try self.validate(self.streamId, name: "streamId", parent: name, min: 26)
            try self.validate(self.streamId, name: "streamId", parent: name, pattern: "^st-[a-zA-Z0-9]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
            case streamId
        }
    }

    public struct GetStreamSessionResponse: AWSDecodableShape {
        /// List of stream details.
        public let streamSession: StreamSession?

        public init(streamSession: StreamSession? = nil) {
            self.streamSession = streamSession
        }

        private enum CodingKeys: String, CodingKey {
            case streamSession
        }
    }

    public struct ImportPlaybackKeyPairRequest: AWSEncodableShape {
        /// Playback-key-pair name. The value does not need to be unique.
        public let name: String?
        /// The public portion of a customer-generated key pair.
        public let publicKeyMaterial: String
        /// Any tags provided with the request are added to the playback key pair tags. See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?

        public init(name: String? = nil, publicKeyMaterial: String, tags: [String: String]? = nil) {
            self.name = name
            self.publicKeyMaterial = publicKeyMaterial
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.name, name: "name", parent: name, max: 128)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9-_]*$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case name
            case publicKeyMaterial
            case tags
        }
    }

    public struct ImportPlaybackKeyPairResponse: AWSDecodableShape {
        public let keyPair: PlaybackKeyPair?

        public init(keyPair: PlaybackKeyPair? = nil) {
            self.keyPair = keyPair
        }

        private enum CodingKeys: String, CodingKey {
            case keyPair
        }
    }

    public struct IngestConfiguration: AWSDecodableShape {
        /// Encoder settings for audio.
        public let audio: AudioConfiguration?
        /// Encoder settings for video.
        public let video: VideoConfiguration?

        public init(audio: AudioConfiguration? = nil, video: VideoConfiguration? = nil) {
            self.audio = audio
            self.video = video
        }

        private enum CodingKeys: String, CodingKey {
            case audio
            case video
        }
    }

    public struct ListChannelsRequest: AWSEncodableShape {
        /// Filters the channel list to match the specified name.
        public let filterByName: String?
        /// Filters the channel list to match the specified recording-configuration ARN.
        public let filterByRecordingConfigurationArn: String?
        /// Maximum number of channels to return. Default: 100.
        public let maxResults: Int?
        /// The first channel to retrieve. This is used for pagination; see the nextToken response field.
        public let nextToken: String?

        public init(filterByName: String? = nil, filterByRecordingConfigurationArn: String? = nil, maxResults: Int? = nil, nextToken: String? = nil) {
            self.filterByName = filterByName
            self.filterByRecordingConfigurationArn = filterByRecordingConfigurationArn
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.filterByName, name: "filterByName", parent: name, max: 128)
            try self.validate(self.filterByName, name: "filterByName", parent: name, pattern: "^[a-zA-Z0-9-_]*$")
            try self.validate(self.filterByRecordingConfigurationArn, name: "filterByRecordingConfigurationArn", parent: name, max: 128)
            try self.validate(self.filterByRecordingConfigurationArn, name: "filterByRecordingConfigurationArn", parent: name, pattern: "^$|^arn:aws:ivs:[a-z0-9-]+:[0-9]+:recording-configuration/[a-zA-Z0-9-]+$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
        }

        private enum CodingKeys: String, CodingKey {
            case filterByName
            case filterByRecordingConfigurationArn
            case maxResults
            case nextToken
        }
    }

    public struct ListChannelsResponse: AWSDecodableShape {
        /// List of the matching channels.
        public let channels: [ChannelSummary]
        /// If there are more channels than maxResults, use nextToken in the request to get the next set.
        public let nextToken: String?

        public init(channels: [ChannelSummary], nextToken: String? = nil) {
            self.channels = channels
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case channels
            case nextToken
        }
    }

    public struct ListPlaybackKeyPairsRequest: AWSEncodableShape {
        /// Maximum number of key pairs to return. Default: your service quota or 100, whichever is smaller.
        public let maxResults: Int?
        /// The first key pair to retrieve. This is used for pagination; see the nextToken response field.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults
            case nextToken
        }
    }

    public struct ListPlaybackKeyPairsResponse: AWSDecodableShape {
        /// List of key pairs.
        public let keyPairs: [PlaybackKeyPairSummary]
        /// If there are more key pairs than maxResults, use nextToken in the request to get the next set.
        public let nextToken: String?

        public init(keyPairs: [PlaybackKeyPairSummary], nextToken: String? = nil) {
            self.keyPairs = keyPairs
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case keyPairs
            case nextToken
        }
    }

    public struct ListRecordingConfigurationsRequest: AWSEncodableShape {
        /// Maximum number of recording configurations to return. Default: your service quota or 100, whichever is smaller.
        public let maxResults: Int?
        /// The first recording configuration to retrieve. This is used for pagination; see the nextToken response field.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults
            case nextToken
        }
    }

    public struct ListRecordingConfigurationsResponse: AWSDecodableShape {
        /// If there are more recording configurations than maxResults, use nextToken in the request to get the next set.
        public let nextToken: String?
        /// List of the matching recording configurations.
        public let recordingConfigurations: [RecordingConfigurationSummary]

        public init(nextToken: String? = nil, recordingConfigurations: [RecordingConfigurationSummary]) {
            self.nextToken = nextToken
            self.recordingConfigurations = recordingConfigurations
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken
            case recordingConfigurations
        }
    }

    public struct ListStreamKeysRequest: AWSEncodableShape {
        /// Channel ARN used to filter the list.
        public let channelArn: String
        /// Maximum number of streamKeys to return. Default: 1.
        public let maxResults: Int?
        /// The first stream key to retrieve. This is used for pagination; see the nextToken response field.
        public let nextToken: String?

        public init(channelArn: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.channelArn = channelArn
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.channelArn, name: "channelArn", parent: name, max: 128)
            try self.validate(self.channelArn, name: "channelArn", parent: name, min: 1)
            try self.validate(self.channelArn, name: "channelArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 50)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
            case maxResults
            case nextToken
        }
    }

    public struct ListStreamKeysResponse: AWSDecodableShape {
        /// If there are more stream keys than maxResults, use nextToken in the request to get the next set.
        public let nextToken: String?
        /// List of stream keys.
        public let streamKeys: [StreamKeySummary]

        public init(nextToken: String? = nil, streamKeys: [StreamKeySummary]) {
            self.nextToken = nextToken
            self.streamKeys = streamKeys
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken
            case streamKeys
        }
    }

    public struct ListStreamSessionsRequest: AWSEncodableShape {
        /// Channel ARN used to filter the list.
        public let channelArn: String
        /// Maximum number of streams to return. Default: 100.
        public let maxResults: Int?
        /// The first stream to retrieve. This is used for pagination; see the nextToken response field.
        public let nextToken: String?

        public init(channelArn: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.channelArn = channelArn
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.channelArn, name: "channelArn", parent: name, max: 128)
            try self.validate(self.channelArn, name: "channelArn", parent: name, min: 1)
            try self.validate(self.channelArn, name: "channelArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
            case maxResults
            case nextToken
        }
    }

    public struct ListStreamSessionsResponse: AWSDecodableShape {
        /// If there are more streams than maxResults, use nextToken in the request to get the next set.
        public let nextToken: String?
        /// List of stream sessions.
        public let streamSessions: [StreamSessionSummary]

        public init(nextToken: String? = nil, streamSessions: [StreamSessionSummary]) {
            self.nextToken = nextToken
            self.streamSessions = streamSessions
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken
            case streamSessions
        }
    }

    public struct ListStreamsRequest: AWSEncodableShape {
        /// Filters the stream list to match the specified criterion.
        public let filterBy: StreamFilters?
        /// Maximum number of streams to return. Default: 100.
        public let maxResults: Int?
        /// The first stream to retrieve. This is used for pagination; see the nextToken response field.
        public let nextToken: String?

        public init(filterBy: StreamFilters? = nil, maxResults: Int? = nil, nextToken: String? = nil) {
            self.filterBy = filterBy
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
        }

        private enum CodingKeys: String, CodingKey {
            case filterBy
            case maxResults
            case nextToken
        }
    }

    public struct ListStreamsResponse: AWSDecodableShape {
        /// If there are more streams than maxResults, use nextToken in the request to get the next set.
        public let nextToken: String?
        /// List of streams.
        public let streams: [StreamSummary]

        public init(nextToken: String? = nil, streams: [StreamSummary]) {
            self.nextToken = nextToken
            self.streams = streams
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken
            case streams
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The ARN of the resource to be retrieved. The ARN must be URL-encoded.
        public let resourceArn: String

        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 128)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 1)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:[a-z-]/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        public let tags: [String: String]

        public init(tags: [String: String]) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct PlaybackKeyPair: AWSDecodableShape {
        /// Key-pair ARN.
        public let arn: String?
        /// Key-pair identifier.
        public let fingerprint: String?
        /// Playback-key-pair name. The value does not need to be unique.
        public let name: String?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?

        public init(arn: String? = nil, fingerprint: String? = nil, name: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.fingerprint = fingerprint
            self.name = name
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case fingerprint
            case name
            case tags
        }
    }

    public struct PlaybackKeyPairSummary: AWSDecodableShape {
        /// Key-pair ARN.
        public let arn: String?
        /// Playback-key-pair name. The value does not need to be unique.
        public let name: String?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?

        public init(arn: String? = nil, name: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.name = name
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case name
            case tags
        }
    }

    public struct PutMetadataRequest: AWSEncodableShape {
        /// ARN of the channel into which metadata is inserted. This channel must have an active stream.
        public let channelArn: String
        /// Metadata to insert into the stream. Maximum: 1 KB per request.
        public let metadata: String

        public init(channelArn: String, metadata: String) {
            self.channelArn = channelArn
            self.metadata = metadata
        }

        public func validate(name: String) throws {
            try self.validate(self.channelArn, name: "channelArn", parent: name, max: 128)
            try self.validate(self.channelArn, name: "channelArn", parent: name, min: 1)
            try self.validate(self.channelArn, name: "channelArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
            try self.validate(self.metadata, name: "metadata", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
            case metadata
        }
    }

    public struct RecordingConfiguration: AWSDecodableShape {
        /// Recording-configuration ARN.
        public let arn: String
        /// A complex type that contains information about where recorded video will be stored.
        public let destinationConfiguration: DestinationConfiguration
        /// Recording-configuration name. The value does not need to be unique.
        public let name: String?
        /// If a broadcast disconnects and then reconnects within the specified interval, the multiple streams will be considered a single broadcast and merged together. Default: 0.
        public let recordingReconnectWindowSeconds: Int?
        /// Indicates the current state of the recording configuration. When the state is ACTIVE, the configuration is ready for recording a channel stream.
        public let state: RecordingConfigurationState
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?
        /// A complex type that allows you to enable/disable the recording of thumbnails for a live session and modify the interval at which thumbnails are generated for the live session.
        public let thumbnailConfiguration: ThumbnailConfiguration?

        public init(arn: String, destinationConfiguration: DestinationConfiguration, name: String? = nil, recordingReconnectWindowSeconds: Int? = nil, state: RecordingConfigurationState, tags: [String: String]? = nil, thumbnailConfiguration: ThumbnailConfiguration? = nil) {
            self.arn = arn
            self.destinationConfiguration = destinationConfiguration
            self.name = name
            self.recordingReconnectWindowSeconds = recordingReconnectWindowSeconds
            self.state = state
            self.tags = tags
            self.thumbnailConfiguration = thumbnailConfiguration
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case destinationConfiguration
            case name
            case recordingReconnectWindowSeconds
            case state
            case tags
            case thumbnailConfiguration
        }
    }

    public struct RecordingConfigurationSummary: AWSDecodableShape {
        /// Recording-configuration ARN.
        public let arn: String
        /// A complex type that contains information about where recorded video will be stored.
        public let destinationConfiguration: DestinationConfiguration
        /// Recording-configuration name. The value does not need to be unique.
        public let name: String?
        /// Indicates the current state of the recording configuration. When the state is ACTIVE, the configuration is ready for recording a channel stream.
        public let state: RecordingConfigurationState
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?

        public init(arn: String, destinationConfiguration: DestinationConfiguration, name: String? = nil, state: RecordingConfigurationState, tags: [String: String]? = nil) {
            self.arn = arn
            self.destinationConfiguration = destinationConfiguration
            self.name = name
            self.state = state
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case destinationConfiguration
            case name
            case state
            case tags
        }
    }

    public struct S3DestinationConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Location (S3 bucket name) where recorded videos will be stored.
        public let bucketName: String

        public init(bucketName: String) {
            self.bucketName = bucketName
        }

        public func validate(name: String) throws {
            try self.validate(self.bucketName, name: "bucketName", parent: name, max: 63)
            try self.validate(self.bucketName, name: "bucketName", parent: name, min: 3)
            try self.validate(self.bucketName, name: "bucketName", parent: name, pattern: "^[a-z0-9-.]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case bucketName
        }
    }

    public struct StopStreamRequest: AWSEncodableShape {
        /// ARN of the channel for which the stream is to be stopped.
        public let channelArn: String

        public init(channelArn: String) {
            self.channelArn = channelArn
        }

        public func validate(name: String) throws {
            try self.validate(self.channelArn, name: "channelArn", parent: name, max: 128)
            try self.validate(self.channelArn, name: "channelArn", parent: name, min: 1)
            try self.validate(self.channelArn, name: "channelArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
        }
    }

    public struct StopStreamResponse: AWSDecodableShape {
        public init() {}
    }

    public struct Stream: AWSDecodableShape {
        /// Channel ARN for the stream.
        public let channelArn: String?
        /// The stream’s health.
        public let health: StreamHealth?
        /// URL of the master playlist, required by the video player to play the HLS stream.
        public let playbackUrl: String?
        /// Time of the stream’s start. This is an ISO 8601 timestamp; note that this is returned as a string.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var startTime: Date?
        /// The stream’s state.
        public let state: StreamState?
        /// Unique identifier for a live or previously live stream in the specified channel.
        public let streamId: String?
        /// A count of concurrent views of the stream. Typically, a new view appears in viewerCount within 15 seconds of when video playback starts and a view is removed from viewerCount within 1 minute of when video playback ends. A value of -1 indicates that the request timed out; in this case, retry.
        public let viewerCount: Int64?

        public init(channelArn: String? = nil, health: StreamHealth? = nil, playbackUrl: String? = nil, startTime: Date? = nil, state: StreamState? = nil, streamId: String? = nil, viewerCount: Int64? = nil) {
            self.channelArn = channelArn
            self.health = health
            self.playbackUrl = playbackUrl
            self.startTime = startTime
            self.state = state
            self.streamId = streamId
            self.viewerCount = viewerCount
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
            case health
            case playbackUrl
            case startTime
            case state
            case streamId
            case viewerCount
        }
    }

    public struct StreamEvent: AWSDecodableShape {
        /// Time when the event occurred. This is an ISO 8601 timestamp; note that this is returned as a string.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var eventTime: Date?
        /// Name that identifies the stream event within a type.
        public let name: String?
        /// Logical group for certain events.
        public let type: String?

        public init(eventTime: Date? = nil, name: String? = nil, type: String? = nil) {
            self.eventTime = eventTime
            self.name = name
            self.type = type
        }

        private enum CodingKeys: String, CodingKey {
            case eventTime
            case name
            case type
        }
    }

    public struct StreamFilters: AWSEncodableShape {
        /// The stream’s health.
        public let health: StreamHealth?

        public init(health: StreamHealth? = nil) {
            self.health = health
        }

        private enum CodingKeys: String, CodingKey {
            case health
        }
    }

    public struct StreamKey: AWSDecodableShape {
        /// Stream-key ARN.
        public let arn: String?
        /// Channel ARN for the stream.
        public let channelArn: String?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?
        /// Stream-key value.
        public let value: String?

        public init(arn: String? = nil, channelArn: String? = nil, tags: [String: String]? = nil, value: String? = nil) {
            self.arn = arn
            self.channelArn = channelArn
            self.tags = tags
            self.value = value
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case channelArn
            case tags
            case value
        }
    }

    public struct StreamKeySummary: AWSDecodableShape {
        /// Stream-key ARN.
        public let arn: String?
        /// Channel ARN for the stream.
        public let channelArn: String?
        /// Array of 1-50 maps, each of the form string:string (key:value). See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]?

        public init(arn: String? = nil, channelArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.channelArn = channelArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case channelArn
            case tags
        }
    }

    public struct StreamSession: AWSDecodableShape {
        /// The properties of the channel at the time of going live.
        public let channel: Channel?
        /// Time when the channel went offline. This is an ISO 8601 timestamp; note that this is returned as a string. For live streams, this is NULL.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var endTime: Date?
        /// The properties of the incoming RTMP stream for the stream.
        public let ingestConfiguration: IngestConfiguration?
        /// The properties of recording the live stream.
        public let recordingConfiguration: RecordingConfiguration?
        /// Time when the channel went live. This is an ISO 8601 timestamp; note that this is returned as a string.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var startTime: Date?
        /// Unique identifier for a live or previously live stream in the specified channel.
        public let streamId: String?
        /// List of Amazon IVS events that the stream encountered. The list is sorted by most recent events and contains up to 500 events. For Amazon IVS events, see Using Amazon EventBridge with Amazon IVS.
        public let truncatedEvents: [StreamEvent]?

        public init(channel: Channel? = nil, endTime: Date? = nil, ingestConfiguration: IngestConfiguration? = nil, recordingConfiguration: RecordingConfiguration? = nil, startTime: Date? = nil, streamId: String? = nil, truncatedEvents: [StreamEvent]? = nil) {
            self.channel = channel
            self.endTime = endTime
            self.ingestConfiguration = ingestConfiguration
            self.recordingConfiguration = recordingConfiguration
            self.startTime = startTime
            self.streamId = streamId
            self.truncatedEvents = truncatedEvents
        }

        private enum CodingKeys: String, CodingKey {
            case channel
            case endTime
            case ingestConfiguration
            case recordingConfiguration
            case startTime
            case streamId
            case truncatedEvents
        }
    }

    public struct StreamSessionSummary: AWSDecodableShape {
        /// Time when the channel went offline. This is an ISO 8601 timestamp; note that this is returned as a string. For live streams, this is NULL.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var endTime: Date?
        /// If true, this stream encountered a quota breach or failure.
        public let hasErrorEvent: Bool?
        /// Time when the channel went live. This is an ISO 8601 timestamp; note that this is returned as a string.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var startTime: Date?
        /// Unique identifier for a live or previously live stream in the specified channel.
        public let streamId: String?

        public init(endTime: Date? = nil, hasErrorEvent: Bool? = nil, startTime: Date? = nil, streamId: String? = nil) {
            self.endTime = endTime
            self.hasErrorEvent = hasErrorEvent
            self.startTime = startTime
            self.streamId = streamId
        }

        private enum CodingKeys: String, CodingKey {
            case endTime
            case hasErrorEvent
            case startTime
            case streamId
        }
    }

    public struct StreamSummary: AWSDecodableShape {
        /// Channel ARN for the stream.
        public let channelArn: String?
        /// The stream’s health.
        public let health: StreamHealth?
        /// Time of the stream’s start. This is an ISO 8601 timestamp; note that this is returned as a string.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var startTime: Date?
        /// The stream’s state.
        public let state: StreamState?
        /// Unique identifier for a live or previously live stream in the specified channel.
        public let streamId: String?
        /// A count of concurrent views of the stream. Typically, a new view appears in viewerCount within 15 seconds of when video playback starts and a view is removed from viewerCount within 1 minute of when video playback ends. A value of -1 indicates that the request timed out; in this case, retry.
        public let viewerCount: Int64?

        public init(channelArn: String? = nil, health: StreamHealth? = nil, startTime: Date? = nil, state: StreamState? = nil, streamId: String? = nil, viewerCount: Int64? = nil) {
            self.channelArn = channelArn
            self.health = health
            self.startTime = startTime
            self.state = state
            self.streamId = streamId
            self.viewerCount = viewerCount
        }

        private enum CodingKeys: String, CodingKey {
            case channelArn
            case health
            case startTime
            case state
            case streamId
            case viewerCount
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// ARN of the resource for which tags are to be added or updated. The ARN must be URL-encoded.
        public let resourceArn: String
        /// Array of tags to be added or updated. See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tags: [String: String]

        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 128)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 1)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:[a-z-]/[a-zA-Z0-9-]+$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct ThumbnailConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Thumbnail recording mode. Default: INTERVAL.
        public let recordingMode: RecordingMode?
        /// The targeted thumbnail-generation interval in seconds. This is configurable (and required) only if recordingMode is INTERVAL. Default: 60.  Important: Setting a value for targetIntervalSeconds does not guarantee that thumbnails are generated at the specified interval. For thumbnails to be generated at the targetIntervalSeconds interval, the IDR/Keyframe value for the input video must be less than the targetIntervalSeconds value. See  Amazon IVS Streaming Configuration for information on setting IDR/Keyframe to the recommended value in video-encoder settings.
        public let targetIntervalSeconds: Int64?

        public init(recordingMode: RecordingMode? = nil, targetIntervalSeconds: Int64? = nil) {
            self.recordingMode = recordingMode
            self.targetIntervalSeconds = targetIntervalSeconds
        }

        public func validate(name: String) throws {
            try self.validate(self.targetIntervalSeconds, name: "targetIntervalSeconds", parent: name, max: 60)
            try self.validate(self.targetIntervalSeconds, name: "targetIntervalSeconds", parent: name, min: 5)
        }

        private enum CodingKeys: String, CodingKey {
            case recordingMode
            case targetIntervalSeconds
        }
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn")),
            AWSMemberEncoding(label: "tagKeys", location: .querystring("tagKeys"))
        ]

        /// ARN of the resource for which tags are to be removed. The ARN must be URL-encoded.
        public let resourceArn: String
        /// Array of tags to be removed. See Tagging Amazon Web Services Resources for more information, including restrictions that apply to tags and "Tag naming limits and requirements"; Amazon IVS has no service-specific constraints beyond what is documented there.
        public let tagKeys: [String]

        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 128)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 1)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:[a-z-]/[a-zA-Z0-9-]+$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 50)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateChannelRequest: AWSEncodableShape {
        /// ARN of the channel to be updated.
        public let arn: String
        /// Whether the channel is private (enabled for playback authorization).
        public let authorized: Bool?
        /// Channel latency mode. Use NORMAL to broadcast and deliver live video up to Full HD. Use LOW for near-real-time interaction with viewers. (Note: In the Amazon IVS console, LOW and NORMAL correspond to Ultra-low and Standard, respectively.)
        public let latencyMode: ChannelLatencyMode?
        /// Channel name.
        public let name: String?
        /// Recording-configuration ARN. If this is set to an empty string, recording is disabled. A value other than an empty string indicates that recording is enabled
        public let recordingConfigurationArn: String?
        /// Channel type, which determines the allowable resolution and bitrate. If you exceed the allowable resolution or bitrate, the stream probably will disconnect immediately. Valid values:    STANDARD: Video is transcoded: multiple qualities are generated from the original input, to automatically give viewers the best experience for their devices and network conditions. Transcoding allows higher playback quality across a range of download speeds. Resolution can be up to 1080p and bitrate can be up to 8.5 Mbps. Audio is transcoded only for renditions 360p and below; above that, audio is passed through. This is the default.    BASIC: Video is transmuxed: Amazon IVS delivers the original input to viewers. The viewer’s video-quality choice is limited to the original input. Resolution can be up to 1080p and bitrate can be up to 1.5 Mbps for 480p and up to 3.5 Mbps for resolutions between 480p and 1080p.
        public let type: ChannelType?

        public init(arn: String, authorized: Bool? = nil, latencyMode: ChannelLatencyMode? = nil, name: String? = nil, recordingConfigurationArn: String? = nil, type: ChannelType? = nil) {
            self.arn = arn
            self.authorized = authorized
            self.latencyMode = latencyMode
            self.name = name
            self.recordingConfigurationArn = recordingConfigurationArn
            self.type = type
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, max: 128)
            try self.validate(self.arn, name: "arn", parent: name, min: 1)
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:[is]vs:[a-z0-9-]+:[0-9]+:channel/[a-zA-Z0-9-]+$")
            try self.validate(self.name, name: "name", parent: name, max: 128)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9-_]*$")
            try self.validate(self.recordingConfigurationArn, name: "recordingConfigurationArn", parent: name, max: 128)
            try self.validate(self.recordingConfigurationArn, name: "recordingConfigurationArn", parent: name, pattern: "^$|^arn:aws:ivs:[a-z0-9-]+:[0-9]+:recording-configuration/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case authorized
            case latencyMode
            case name
            case recordingConfigurationArn
            case type
        }
    }

    public struct UpdateChannelResponse: AWSDecodableShape {
        public let channel: Channel?

        public init(channel: Channel? = nil) {
            self.channel = channel
        }

        private enum CodingKeys: String, CodingKey {
            case channel
        }
    }

    public struct VideoConfiguration: AWSDecodableShape {
        /// Indicates the degree of required decoder performance for a profile. Normally this is set automatically by the encoder. For details, see the H.264 specification.
        public let avcLevel: String?
        /// Indicates to the decoder the requirements for decoding the stream. For definitions of the valid values, see the H.264 specification.
        public let avcProfile: String?
        /// Codec used for the video encoding.
        public let codec: String?
        /// Software or hardware used to encode the video.
        public let encoder: String?
        /// The expected ingest bitrate (bits per second). This is configured in the encoder.
        public let targetBitrate: Int64?
        /// The expected ingest framerate. This is configured in the encoder.
        public let targetFramerate: Int64?
        /// Video-resolution height in pixels.
        public let videoHeight: Int64?
        /// Video-resolution width in pixels.
        public let videoWidth: Int64?

        public init(avcLevel: String? = nil, avcProfile: String? = nil, codec: String? = nil, encoder: String? = nil, targetBitrate: Int64? = nil, targetFramerate: Int64? = nil, videoHeight: Int64? = nil, videoWidth: Int64? = nil) {
            self.avcLevel = avcLevel
            self.avcProfile = avcProfile
            self.codec = codec
            self.encoder = encoder
            self.targetBitrate = targetBitrate
            self.targetFramerate = targetFramerate
            self.videoHeight = videoHeight
            self.videoWidth = videoWidth
        }

        private enum CodingKeys: String, CodingKey {
            case avcLevel
            case avcProfile
            case codec
            case encoder
            case targetBitrate
            case targetFramerate
            case videoHeight
            case videoWidth
        }
    }
}

// MARK: - Errors

/// Error enum for IVS
public struct IVSErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case channelNotBroadcasting = "ChannelNotBroadcasting"
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case pendingVerification = "PendingVerification"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case streamUnavailable = "StreamUnavailable"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize IVS
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    public static var channelNotBroadcasting: Self { .init(.channelNotBroadcasting) }
    public static var conflictException: Self { .init(.conflictException) }
    public static var internalServerException: Self { .init(.internalServerException) }
    public static var pendingVerification: Self { .init(.pendingVerification) }
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    public static var streamUnavailable: Self { .init(.streamUnavailable) }
    public static var throttlingException: Self { .init(.throttlingException) }
    public static var validationException: Self { .init(.validationException) }
}

extension IVSErrorType: Equatable {
    public static func == (lhs: IVSErrorType, rhs: IVSErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension IVSErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
